package com.lagou.zookeeperhomework;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lagou.zookeeperhomework.entity.JDBCConfig;
import com.lagou.zookeeperhomework.entity.ZkStrSerializer;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;

@SpringBootApplication
public class ZookeeperHomeworkApplication {

    //数据库配置连接
    private static HikariDataSource hikariDataSource;

    //Zk客户端
    private static ZkClient zkClient;

    //数据操作对象
    private static ObjectMapper mapper = new ObjectMapper();

    public static void main(String[] args) throws IOException {

        SpringApplication.run(ZookeeperHomeworkApplication.class, args);

        //初始化zookeeper，建立节点并配置监听器
        initZk();

        //获取配置信息创建连接池
        configHikariSource();

    }


    //初始化zk
    private static void initZk() {

        zkClient = new ZkClient("linux121:2181,linux122:2181");

        zkClient.setZkSerializer(new ZkStrSerializer());

        boolean exists = zkClient.exists("/jdbc");

        if (!exists) {
            zkClient.createEphemeral("/jdbc", "{\"url\":\"jdbc:mysql://192.168.80.123:3306/sqoop?useUnicode=true&characterEncoding=utf8\"," +
                    "\"username\":\"root\"," +
                    "\"password\":\"12345678\"}");
        }

        //监听配置信息是否变化
        zkClient.subscribeDataChanges("/jdbc", new IZkDataListener() {

            public void handleDataChange(String path, Object data) throws IOException {

                System.out.println(path + " data is changed, new data " + data);

                //释放连接池
                hikariDataSource.close();

                //创建新的连接池
                configHikariSource();
            }

            public void handleDataDeleted(String path) {

                System.out.println(path + " is deleted!!");

                hikariDataSource.close();
            }
        });
    }

    /**
     * 配置数据库连接池
     * 1. 从 zookeeper 中获取配置信息
     * 2. 更新 hikari 配置
     * 3. 获取连接信息
     */
    private static void configHikariSource() throws IOException {

        JDBCConfig myConfig = getJDBCConfig();

        updateHikariConfig(myConfig);

        try {

            executeConnect();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    //执行连接Mysql
    private static void executeConnect() throws SQLException {

        Connection connection = hikariDataSource.getConnection();

        DatabaseMetaData metaData = connection.getMetaData();

        System.out.println("测试连接池获取连接");
        System.out.println("数据库URL: " + metaData.getURL());
        System.out.println("数据库已知的用户: " + metaData.getUserName());

    }

    //更新数据库信息
    private static void updateHikariConfig(JDBCConfig myConfig) {

        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(myConfig.getUrl());
        config.setUsername(myConfig.getUsername());
        config.setPassword(myConfig.getPassword());
        config.addDataSourceProperty("driverClassName", myConfig.getDriver());
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        hikariDataSource = new HikariDataSource(config);
    }

    private static JDBCConfig getJDBCConfig() throws IOException {

        Object data = zkClient.readData("/jdbc");

        try {
            JDBCConfig myConfig = mapper.readValue(data.toString(), JDBCConfig.class);

            System.out.println(myConfig.toString());

            return myConfig;

        } catch (JsonProcessingException e) {

            return new JDBCConfig();
        }
    }


}
